export var evaluate = function (expression) {
  const scope = new Map()
  let vars = []
  let start = 0,
    n = expression.length
  const stack = []
  let cur = new Expr(ExprStatus.VALUE)

  while (start < n) {
    if (expression[start] === ' ') {
      start++ // 去掉空格
      continue
    }
    if (expression[start] === '(') {
      start++ // 去掉左括号
      stack.push(cur)
      cur = new Expr(ExprStatus.NONE)
      continue
    }
    let sb = ''
    if (expression[start] === ')') {
      // 本质上是把表达式转成一个 token
      start++ // 去掉右括号
      if (cur.status == ExprStatus.LET2) {
        sb = cur.value
        for (const v of vars[vars.length - 1]) {
          // 清除作用域
          scope.get(v).pop()
        }
        vars.pop()
      } else if (cur.status === ExprStatus.ADD2) {
        sb = cur.e1 + cur.e2
      } else {
        sb = cur.e1 * cur.e2
      }
      cur = stack.pop() // 获取上层状态
    } else {
      while (start < n && expression[start] !== ' ' && expression[start] !== ')') {
        sb += expression[start]
        start++
      }
    }
    let token = sb
    switch (cur.status) {
      case 'VALUE':
        cur.value = parseInt(token)
        cur.status = ExprStatus.DONE
        break
      case 'NONE':
        if ('let' === token) {
          cur.status = ExprStatus.LET
          vars.push([]) // 记录该层作用域的所有变量, 方便后续的清除
        } else if ('add' === token) {
          cur.status = ExprStatus.ADD
        } else if ('mult' === token) {
          cur.status = ExprStatus.MULT
        }
        break
      case 'LET':
        if (expression[start] === ')') {
          // let 表达式的最后一个 expr 表达式
          cur.value = calculateToken(scope, token)
          cur.status = ExprStatus.LET2
        } else {
          cur.v = token
          vars[vars.length - 1].push(token) // 记录该层作用域的所有变量, 方便后续的清除
          cur.status = ExprStatus.LET1
        }
        break
      case 'LET1':
        if (!scope.has(cur.v)) {
          scope.set(cur.v, [])
        }
        scope.get(cur.v).push(calculateToken(scope, token))
        cur.status = ExprStatus.LET
        break
      case 'ADD':
        cur.e1 = calculateToken(scope, token)
        cur.status = ExprStatus.ADD1
        break
      case 'ADD1':
        cur.e2 = calculateToken(scope, token)
        cur.status = ExprStatus.ADD2
        break
      case 'MULT':
        cur.e1 = calculateToken(scope, token)
        cur.status = ExprStatus.MULT1
        break
      case 'MULT1':
        cur.e2 = calculateToken(scope, token)
        cur.status = ExprStatus.MULT2
        break
    }
  }
  return cur.value
}

const calculateToken = (scope, token) => {
  if (token[0] >= 'a' && token[0] <= 'z') {
    const n = scope.get(token).length
    return scope.get(token)[n - 1]
  } else {
    return parseInt(token)
  }
}

var ExprStatus = {
  VALUE: 'VALUE', // 初始状态
  NONE: 'NONE', // 表达式类型未知
  LET: 'LET', // let 表达式
  LET1: 'LET1', // let 表达式已经解析了 vi 变量
  LET2: 'LET2', // let 表达式已经解析了最后一个表达式 expr
  ADD: 'ADD', // add 表达式
  ADD1: 'ADD1', // add 表达式已经解析了 e1 表达式
  ADD2: 'ADD2', // add 表达式已经解析了 e2 表达式
  MULT: 'MULT', // mult 表达式
  MULT1: 'MULT1', // mult 表达式已经解析了 e1 表达式
  MULT2: 'MULT2', // mult 表达式已经解析了 e2 表达式
  DONE: 'DONE', // 解析完成
}

class Expr {
  constructor(s) {
    this.status = s
    this.v = '' // let 的变量 vi
    this.value = 0 // VALUE 状态的数值，或者 LET2 状态最后一个表达式的数值
    this.e1 = 0 // add 或 mult 表达式的两个表达式 e1 和 e2 的数值
    this.e2 = 0
  }
}
